package com.bzkj.basicinfo.service.impl.warehouse;

import com.bzkj.basicinfo.domain.warehouse.BarRelation;
import com.bzkj.basicinfo.domain.warehouse.PdaBillsList;
import com.bzkj.basicinfo.domain.warehouse.PdaMsfxBardata;
import com.bzkj.basicinfo.domain.warehouse.PdaWarehouseBillsDetail;
import com.bzkj.basicinfo.domain.warehouse.dto.BillsExportDto;
import com.bzkj.basicinfo.domain.warehouse.dto.YiLianYunMaResponse;
import com.bzkj.basicinfo.mapper.BarRelationMapper;
import com.bzkj.basicinfo.mapper.PdaBillsListMapper;
import com.bzkj.basicinfo.mapper.PdaMsfxBardataMapper;
import com.bzkj.basicinfo.mapper.PdaMsfxCustomerMapper;
import com.bzkj.basicinfo.service.warehouse.IPdaBillsListService;
import com.bzkj.basicinfo.service.warehouse.IYiLianYunMaService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.bzkj.common.utils.StringUtils;
import com.bzkj.common.utils.poi.ExcelUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 单据主表Service业务层处理
 * 
 * @author lixinyu1
 * @date 2025-06-13
 */
@Service
public class PdaBillsListServiceImpl implements IPdaBillsListService
{
    private static final Logger log = LoggerFactory.getLogger(PdaBillsListServiceImpl.class);

    @Resource
    private PdaBillsListMapper pdaBillsListMapper;

    @Resource
    private PdaMsfxBardataMapper pdaMsfxBardataMapper;

    @Resource
    private BarRelationMapper barRelationMapper;

    @Resource
    private IYiLianYunMaService yiLianYunMaService;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private PdaMsfxCustomerMapper pdaMsfxCustomerMapper;

    @Value("${soapUrl}")
    private String SOAP_URL;


    /**
     * 查询单据主表
     * 
     * @param BillsID 单据主表主键
     * @return 单据主表
     */
    @Override
    public PdaBillsList selectPdaBillsListByBillsID(String BillsID)
    {
        PdaBillsList pdaBillsList = pdaBillsListMapper.selectPdaBillsListByBillsID(BillsID);
        if(pdaBillsList != null){
            List<PdaWarehouseBillsDetail> pdaWarehouseBillsDetailList = pdaBillsList.getPdaWarehouseBillsDetailList();
            if(pdaWarehouseBillsDetailList != null && !pdaWarehouseBillsDetailList.isEmpty()){
                //获取数量信息
                for(PdaWarehouseBillsDetail pdaWarehouseBillsDetail : pdaWarehouseBillsDetailList){
                    if(StringUtils.isEmpty(pdaWarehouseBillsDetail.getDrugNum())&&StringUtils.isEmpty(pdaWarehouseBillsDetail.getDrugCheckNum())){
                        List<PdaMsfxBardata> bardataList = pdaMsfxBardataMapper.selectBarcodesByBillsIDAndDrugID(pdaWarehouseBillsDetail.getBillsID(),pdaWarehouseBillsDetail.getDrugBatchNo(),pdaWarehouseBillsDetail.getDrugID());
                        //遍历list将barNum的值相加
                        int totalBarNum = bardataList.stream().mapToInt(PdaMsfxBardata::getBarNum).sum();
                        pdaWarehouseBillsDetail.setDrugNum(String.valueOf(totalBarNum));
                        pdaWarehouseBillsDetail.setDrugCheckNum(String.valueOf(totalBarNum));
                    }
                }
            }
        }
        return pdaBillsList;
    }


    /**
     * 查询单据明细列表（以批次号和药品名称为主）
     *
     * @param pdaBillsList 单据主表
     * @return 单据明细
     */
    @Override
    public List<PdaBillsList> selectPdaBillsDetailList(PdaBillsList pdaBillsList)
    {
        return pdaBillsListMapper.selectPdaBillsDetailList(pdaBillsList);
    }

    /**
     * 新增单据主表
     * 
     * @param pdaBillsList 单据主表
     * @return 结果
     */
    @Transactional
    @Override
    public int insertPdaBillsList(PdaBillsList pdaBillsList)
    {
        int rows = pdaBillsListMapper.insertPdaBillsList(pdaBillsList);
        insertPdaWarehouseBillsDetail(pdaBillsList);
        return rows;
    }

    /**
     * 修改单据主表
     * 
     * @param pdaBillsList 单据主表
     * @return 结果
     */
    @Transactional
    @Override
    public int updatePdaBillsList(PdaBillsList pdaBillsList)
    {
        pdaBillsListMapper.deletePdaWarehouseBillsDetailByBillsID(pdaBillsList.getBillsID());
        insertPdaWarehouseBillsDetail(pdaBillsList);
        return pdaBillsListMapper.updatePdaBillsList(pdaBillsList);
    }

    /**
     * 批量删除单据主表
     * 
     * @param BillsIDs 需要删除的单据主表主键
     * @return 结果
     */
    @Transactional
    @Override
    public int deletePdaBillsListByBillsIDs(String[] BillsIDs)
    {
        pdaBillsListMapper.deletePdaWarehouseBillsDetailByBillsIDs(BillsIDs);
        return pdaBillsListMapper.deletePdaBillsListByBillsIDs(BillsIDs);
    }


    /**
     * 新增单据明细信息
     * 
     * @param pdaBillsList 单据主表对象
     */
    public void insertPdaWarehouseBillsDetail(PdaBillsList pdaBillsList)
    {
        List<PdaWarehouseBillsDetail> pdaWarehouseBillsDetailList = pdaBillsList.getPdaWarehouseBillsDetailList();
        String BillsID = pdaBillsList.getBillsID();
        if (StringUtils.isNotNull(pdaWarehouseBillsDetailList))
        {
            List<PdaWarehouseBillsDetail> list = new ArrayList<PdaWarehouseBillsDetail>();
            for (PdaWarehouseBillsDetail pdaWarehouseBillsDetail : pdaWarehouseBillsDetailList)
            {
                pdaWarehouseBillsDetail.setBillsID(BillsID);
                list.add(pdaWarehouseBillsDetail);
            }
            if (list.size() > 0)
            {
                pdaBillsListMapper.batchPdaWarehouseBillsDetail(list);
            }
        }
    }

    /**
     * 更新单据上传状态
     *
     * @param billsID 单据号
     * @param uploadState 上传状态
     * @return 结果
     */
    @Override
    public int updateUploadState(String billsID, String uploadState)
    {
        return pdaBillsListMapper.updateUploadState(billsID, uploadState);
    }

    /**
     * 软删除单据主表（将状态改为3）
     *
     * @param billsIDs 需要删除的单据主表主键集合
     * @return 结果
     */
    @Override
    public int softDeletePdaBillsList(String[] billsIDs)
    {
        return pdaBillsListMapper.softDeletePdaBillsList(billsIDs);
    }

    /**
     * 上传单据到易联云码平台
     *
     * @param billsID 单据号
     * @param institutionData 医疗机构信息
     * @return 结果
     */
    @Override
    public boolean uploadBillsToYiLianYunMa(String billsID, Map<String, String> institutionData)
    {
        try
        {
            log.info("开始上传单据到易联云码平台，单据号: {}", billsID);

            // 获取单据详细信息（包含明细）
            PdaBillsList pdaBillsList = pdaBillsListMapper.selectPdaBillsListByBillsID(billsID);
            if (pdaBillsList == null)
            {
                log.error("单据不存在，单据号: {}", billsID);
                updateUploadState(billsID, "2"); // 上传失败
                return false;
            }

            // 设置医疗机构信息
            if (institutionData != null && !institutionData.isEmpty()) {
                pdaBillsList.setInstitutionId(institutionData.get("institutionId"));
                pdaBillsList.setInstitutionName(institutionData.get("institutionName"));
            }

            // 调用易联云码平台接口
            YiLianYunMaResponse response = yiLianYunMaService.uploadBills(pdaBillsList);

            if (response != null && response.isSuccess())
            {
                log.info("上传单据到易联云码平台成功，单据号: {}", billsID);
                updateUploadState(billsID, "1"); // 上传成功
                return true;
            }
            else
            {
                String errorMsg = response != null ? response.getMsg() : "未知错误";
                log.error("上传单据到易联云码平台失败，单据号: {}, 错误信息: {}", billsID, errorMsg);
                updateUploadState(billsID, "2"); // 上传失败
                return false;
            }
        }
        catch (Exception e)
        {
            log.error("上传单据到易联云码平台异常，单据号: {}", billsID, e);
            updateUploadState(billsID, "2"); // 上传失败
            return false;
        }
    }

    /**
     * 获取首页统计数据
     *
     * @return 统计数据
     */
    @Override
    public Map<String, Object> getDashboardStatistics()
    {
        Map<String, Object> statistics = new HashMap<>();

        // 统计单据总数量
        int totalBills = pdaBillsListMapper.countTotalBills();
        statistics.put("totalBills", totalBills);

        // 统计上传成功数量
        int uploadSuccessCount = pdaBillsListMapper.countBillsByUploadState("1");
        statistics.put("uploadSuccessCount", uploadSuccessCount);

        // 统计上传失败数量
        int uploadFailCount = pdaBillsListMapper.countBillsByUploadState("2");
        statistics.put("uploadFailCount", uploadFailCount);

        // 统计未上传数量
        int notUploadedCount = pdaBillsListMapper.countBillsByUploadState("0");
        statistics.put("notUploadedCount", notUploadedCount);

        // 按单据类型统计
        List<Map<String, Object>> billsTypeStats = pdaBillsListMapper.countBillsByType();
        statistics.put("billsTypeStats", billsTypeStats);

        return statistics;
    }


    /**
     * 获取单据二维码信息
     *
     * @param billsID 单据号
     * @return 二维码信息列表
     */
    @Override
    public List<PdaMsfxBardata> getQrCodeInfoByBillsID(String billsID)
    {
        try
        {
            // 获取单据详细信息
            PdaBillsList pdaBillsList = pdaBillsListMapper.selectPdaBillsListByBillsID(billsID);
            if (pdaBillsList == null || pdaBillsList.getPdaWarehouseBillsDetailList() == null)
            {
                log.warn("单据不存在或无明细信息，单据号: {}", billsID);
                return new ArrayList<>();
            }

            // 收集所有药品ID
            List<String> drugIDs = pdaBillsList.getPdaWarehouseBillsDetailList().stream()
                .map(PdaWarehouseBillsDetail::getDrugID)
                .filter(StringUtils::isNotEmpty)
                .distinct()
                .collect(Collectors.toList());

            if (drugIDs.isEmpty())
            {
                log.warn("单据明细中没有有效的药品ID，单据号: {}", billsID);
                return new ArrayList<>();
            }

            // 查询二维码信息
            List<PdaMsfxBardata> qrCodeList = pdaMsfxBardataMapper.selectBarcodesByDrugIDs(drugIDs);
            log.info("获取到二维码信息数量: {}, 单据号: {}", qrCodeList.size(), billsID);

            return qrCodeList;
        }
        catch (Exception e)
        {
            log.error("获取单据二维码信息失败，单据号: {}", billsID, e);
            return new ArrayList<>();
        }
    }


    /**
     * 根据单据ID和药品ID获取层级结构的二维码信息
     *
     * @param billsID 单据ID
     * @param drugID 药品ID
     * @return 层级结构的二维码信息
     */
    @Override
    public Map<String, Object> getQrCodeHierarchyByBillsIDAndDrugID(String billsID,String drugBatchNo, String drugID)
    {
        try
        {
            log.info("开始查询单据药品层级二维码信息，单据ID: {}, 药品ID: {}", billsID, drugID);
            log.info("参数类型检查 - billsID: {}, drugID: {}", billsID != null ? billsID.getClass().getSimpleName() : "null",
                drugID != null ? drugID.getClass().getSimpleName() : "null");

            List<PdaMsfxBardata> allBarcodes = new ArrayList<>();

            // 1. 首先尝试精确匹配：根据单据ID和药品ID查询
            try {
                allBarcodes = pdaMsfxBardataMapper.selectBarcodesByBillsIDAndDrugID(billsID,drugBatchNo, drugID);
                log.info("精确匹配查询结果数量: {}", allBarcodes != null ? allBarcodes.size() : 0);
            } catch (Exception e) {
                log.error("精确匹配查询失败", e);
                allBarcodes = new ArrayList<>();
            }


            if (allBarcodes.isEmpty())
            {
                log.warn("所有查询方式都未找到二维码信息，单据ID: {}, 药品ID: {}", billsID, drugID);
                return createEmptyHierarchy();
            }

            // 记录找到的数据详情
            for (PdaMsfxBardata barcode : allBarcodes) {
                log.info("找到追溯码数据: 单据ID={}, 药品ID={}, 追溯码={}, 级别={}",
                    barcode.getCorporderid(), barcode.getDrugid(), barcode.getBarcode(), barcode.getCodelevel());
            }

            // 构建层级结构
            Map<String, Object> hierarchy = buildQrCodeHierarchy(allBarcodes);

            log.info("单据药品层级二维码信息查询完成，单据ID: {}, 药品ID: {}, 返回数据量: {}",
                billsID, drugID, allBarcodes.size());
            return hierarchy;
        }
        catch (Exception e)
        {
            log.error("查询单据药品层级二维码信息失败，单据ID: {}, 药品ID: {}", billsID, drugID, e);
            return createEmptyHierarchy();
        }
    }

    /**
     * 构建二维码层级结构
     */
    private Map<String, Object> buildQrCodeHierarchy(List<PdaMsfxBardata> allBarcodes)
    {
        Map<String, Object> result = new HashMap<>();

        // 按级别分组
        Map<Integer, List<PdaMsfxBardata>> levelGroups = allBarcodes.stream()
            .collect(Collectors.groupingBy(PdaMsfxBardata::getCodelevel));

        // 找到最高级别和最低级别
        Integer maxLevel = levelGroups.keySet().stream().max(Integer::compareTo).orElse(1);
        Integer minLevel = levelGroups.keySet().stream().min(Integer::compareTo).orElse(1);

        result.put("maxLevel", maxLevel);
        result.put("minLevel", minLevel);
        result.put("totalCount", allBarcodes.size());
        result.put("levelGroups", levelGroups);

        // 构建层级数据列表，包含所有存在的级别
        List<Map<String, Object>> levelData = new ArrayList<>();

        // 按级别从低到高排序，构建每个级别的数据
        for (int level = minLevel; level <= maxLevel; level++) {
            if (levelGroups.containsKey(level)) {
                Map<String, Object> levelInfo = new HashMap<>();
                levelInfo.put("level", level);
                levelInfo.put("codes", levelGroups.get(level));
                levelInfo.put("count", levelGroups.get(level).size());

                // 级别1不能查看子级，级别2及以上可以查看子级
                levelInfo.put("canViewChildren", level >= 2);

                // 判断是否有子级（当前级别不是最高级别时）
                levelInfo.put("hasChildren", level < maxLevel);

                levelData.add(levelInfo);
            }
        }

        result.put("levelData", levelData);

        // 设置类型
        if (maxLevel == 1) {
            result.put("type", "LEVEL_1_ONLY");
        } else {
            result.put("type", "MULTI_LEVEL");
        }

        return result;
    }

    /**
     * 创建空的层级结构
     */
    private Map<String, Object> createEmptyHierarchy()
    {
        Map<String, Object> result = new HashMap<>();
        result.put("maxLevel", 0);
        result.put("totalCount", 0);
        result.put("type", "EMPTY");
        result.put("codes", new ArrayList<>());
        result.put("hasChildren", false);
        return result;
    }

    /**
     * 根据父级码获取子码（用于前端点击展开，去重处理）
     */
    @Override
    public List<PdaMsfxBardata> getChildCodesByParentCode(String parentCode)
    {
        try
        {
            log.info("查询子码，父级码: {}", parentCode);

            List<String> parentCodes = Arrays.asList(parentCode);
            List<BarRelation> barRelations = barRelationMapper.selectCurCodesByParentCodes(parentCodes);

            // 使用LinkedHashMap去重，保持插入顺序
            Map<String, PdaMsfxBardata> childCodeMap = new LinkedHashMap<>();

            if (barRelations != null && !barRelations.isEmpty())
            {
                for (BarRelation relation : barRelations)
                {
                    String curCode = relation.getCurCode();

                    // 检查是否已存在该子码
                    if (!childCodeMap.containsKey(curCode))
                    {
                        PdaMsfxBardata childCode = new PdaMsfxBardata();
                        childCode.setBarcode(curCode);
                        childCode.setCodelevel(Integer.parseInt(relation.getCodeLevel()));
                        childCode.setScantime(relation.getScanTime());
                        childCode.setBarstate("0");
                        childCode.setOrderstate("0");

                        childCodeMap.put(curCode, childCode);
                        log.debug("添加子码: {} (级别: {})", curCode, relation.getCodeLevel());
                    }
                    else
                    {
                        log.debug("子码{}已存在，跳过重复添加", curCode);
                    }
                }

                log.info("找到子码数量: {} (去重前: {})", childCodeMap.size(), barRelations.size());
            }

            // 转换为List返回
            return new ArrayList<>(childCodeMap.values());
        }
        catch (Exception e)
        {
            log.error("查询子码失败，父级码: {}", parentCode, e);
            return new ArrayList<>();
        }
    }

    /**
     * 批量导出选中的单据数据（包含明细和追溯码信息）
     *
     * @param response HTTP响应
     * @param billsIDs 单据ID数组   使用
     */
    @Override
    public void exportSelectedBillsWithDetails(HttpServletResponse response, String[] billsIDs)
    {
        try
        {
            // 设置更严格的批量导出限制，避免超时
            log.info("开始批量导出选中的单据数据，单据数量: {}", billsIDs.length);

            // 创建导出数据列表
            List<BillsExportDto> exportDataList = new ArrayList<>();

            // 分批处理选中的单据
            int batchSize = 5; // 减少每批处理数量到5条单据
            for (int i = 0; i < billsIDs.length; i += batchSize) {
                int endIndex = Math.min(i + batchSize, billsIDs.length);
                String[] batchBillsIDs = Arrays.copyOfRange(billsIDs, i, endIndex);

                log.info("处理第 {} 批选中单据，范围: {}-{}", (i / batchSize + 1), i + 1, endIndex);

                for (String billsID : batchBillsIDs) {
                    if (StringUtils.isEmpty(billsID)) {
                        continue;
                    }

                    // 获取单据详细信息（包含明细）
                    PdaBillsList detailBills = pdaBillsListMapper.selectPdaBillsListByBillsID(billsID.trim());

                    if (detailBills != null) {
                        if (detailBills.getPdaWarehouseBillsDetailList() != null && !detailBills.getPdaWarehouseBillsDetailList().isEmpty()) {
                            // 为每个明细查询一级码，每个一级码一行
                            for (PdaWarehouseBillsDetail detail : detailBills.getPdaWarehouseBillsDetailList()) {
                                try {
                                    // 查询该明细的所有码信息，按一级码分组导出
                                    List<BillsExportDto> drugExportData = createExportDataForDrug(detailBills, detail);

                                    if (drugExportData == null || drugExportData.isEmpty()) {
                                        // 没有码，导出一行空数据
                                        BillsExportDto exportData = createExportDataForSingleCode(detailBills, detail, "", "", "", "");
                                        exportDataList.add(exportData);
                                    } else {
                                        // 添加所有导出数据
                                        exportDataList.addAll(drugExportData);
                                    }
                                } catch (Exception e) {
                                    log.error("处理明细 {} 时发生错误，跳过该明细: {}", detail.getDrugID(), e.getMessage());
                                }
                            }
                        } else {
                            // 如果没有明细，只导出主表信息
                            BillsExportDto exportData = createExportDataForSingleCode(detailBills, null, "", "", "", "");
                            exportDataList.add(exportData);
                        }
                    } else {
                        log.warn("未找到单据信息，单据ID: {}", billsID);
                    }
                }
            }

            if (exportDataList.isEmpty())
            {
                throw new RuntimeException("没有找到可导出的数据");
            }

            // 使用ExcelUtil导出
            ExcelUtil<BillsExportDto> util = new ExcelUtil<>(BillsExportDto.class);
            util.exportExcel(response, exportDataList, "药品追溯码数据", "银杏林药业有限责任公司药品追溯码数据", "药品追溯码数据");

            log.info("批量导出完成，导出数据行数: {}", exportDataList.size());
        }
        catch (Exception e)
        {
            log.error("批量导出选中单据数据失败", e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
    }


    /**
     * 为药品创建导出数据（按照正确的业务逻辑，去重一级追溯码）
     *
     * @param bills 单据信息
     * @param detail 明细信息
     * @return 导出数据列表
     */
    private List<BillsExportDto> createExportDataForDrug(PdaBillsList bills, PdaWarehouseBillsDetail detail) {
        List<BillsExportDto> result = new ArrayList<>();

        try {
            log.debug("开始为药品{}创建导出数据，单据号: {}", detail.getDrugID(), bills.getBillsID());

            // 使用单据号和药品ID查询该药品的所有级别码+批次号
            List<PdaMsfxBardata> allBarcodes = pdaMsfxBardataMapper.selectBarcodesByBillsIDAndDrugID(bills.getBillsID(),detail.getDrugBatchNo(), detail.getDrugID());

            if (allBarcodes == null || allBarcodes.isEmpty()) {
                log.debug("单据{}药品{}没有码信息", bills.getBillsID(), detail.getDrugID());
                return result;
            }

            // 按级别分组
            Map<Integer, List<PdaMsfxBardata>> levelGroups = allBarcodes.stream()
                .filter(barcode -> StringUtils.isNotEmpty(barcode.getBarcode()))
                .collect(Collectors.groupingBy(PdaMsfxBardata::getCodelevel));

            log.debug("单据{}药品{}的码分组情况: {}", bills.getBillsID(), detail.getDrugID(),
                levelGroups.entrySet().stream()
                    .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().size())));

            // 用于去重的一级码集合，存储已处理的一级码及其对应的导出数据
            Map<String, BillsExportDto> level1CodeMap = new LinkedHashMap<>();

            // 1. 处理一级码：直接输出，每个一级码一行（去重）
            List<PdaMsfxBardata> level1Codes = levelGroups.getOrDefault(1, new ArrayList<>());
            for (PdaMsfxBardata level1Barcode : level1Codes) {
                String level1Code = level1Barcode.getBarcode();
                if (!level1CodeMap.containsKey(level1Code)) {
                    BillsExportDto exportData = createExportDataForSingleCode(
                        bills, detail, level1Code, "", "", ""
                    );
                    level1CodeMap.put(level1Code, exportData);
                    log.debug("添加一级码: {}", level1Code);
                } else {
                    log.debug("一级码{}已存在，跳过重复添加", level1Code);
                }
            }

            // 2. 处理二级码：查询BarRelation表获取子码（一级码），每个子码一行（去重）
            List<PdaMsfxBardata> level2Codes = levelGroups.getOrDefault(2, new ArrayList<>());
            for (PdaMsfxBardata level2Barcode : level2Codes) {
                List<String> childLevel1Codes = getChildLevel1Codes(level2Barcode.getBarcode());
                boolean hasValidChild = false;

                for (String childCode : childLevel1Codes) {
                    if (!level1CodeMap.containsKey(childCode)) {
                        BillsExportDto exportData = createExportDataForSingleCode(
                            bills, detail, childCode, level2Barcode.getBarcode(), "", ""
                        );
                        level1CodeMap.put(childCode, exportData);
                        hasValidChild = true;
                        log.debug("添加二级码{}的子码: {}", level2Barcode.getBarcode(), childCode);
                    } else {
                        // 如果一级码已存在，更新其二级码信息（如果当前二级码信息为空）
                        BillsExportDto existingData = level1CodeMap.get(childCode);
                        if (StringUtils.isEmpty(existingData.getLevel2Codes())) {
                            existingData.setLevel2Codes(level2Barcode.getBarcode());
                            log.debug("更新一级码{}的二级码信息: {}", childCode, level2Barcode.getBarcode());
                        }
                        hasValidChild = true;
                        log.debug("一级码{}已存在，跳过重复添加，但更新二级码信息", childCode);
                    }
                }

                if(childLevel1Codes.isEmpty()){
                    //说明只有二级码没有一级码 那么只需要导出二级码数据即可
                    String level2Key = "L2_" + level2Barcode.getBarcode(); // 使用特殊前缀避免与一级码冲突
                    if (!level1CodeMap.containsKey(level2Key)) {
                        BillsExportDto exportData = createExportDataForSingleCode(
                                bills, detail, "", level2Barcode.getBarcode(), "", ""
                        );
                        level1CodeMap.put(level2Key, exportData);
                        log.debug("添加二级码{}", level2Barcode.getBarcode());
                    }
                }
            }

            // 3. 处理三级码：递归查询到一级码，每个一级码一行（去重）
            List<PdaMsfxBardata> level3Codes = levelGroups.getOrDefault(3, new ArrayList<>());
            for (PdaMsfxBardata level3Barcode : level3Codes) {
                List<CodePathInfo> codePathInfos = getChildLevel1CodesWithPath(level3Barcode.getBarcode(), 3);
                boolean hasValidChild = false;

                for (CodePathInfo pathInfo : codePathInfos) {
                    String level1Code = pathInfo.getLevel1Code();
                    if (!level1CodeMap.containsKey(level1Code)) {
                        BillsExportDto exportData = createExportDataForSingleCode(
                            bills, detail, level1Code, pathInfo.getLevel2Code(), level3Barcode.getBarcode(), ""
                        );
                        level1CodeMap.put(level1Code, exportData);
                        hasValidChild = true;
                        log.debug("添加三级码{}的子码: {} (经过二级码: {})", level3Barcode.getBarcode(), level1Code, pathInfo.getLevel2Code());
                    } else {
                        // 如果一级码已存在，更新其二级码和三级码信息（如果当前信息为空）
                        BillsExportDto existingData = level1CodeMap.get(level1Code);
                        if (StringUtils.isEmpty(existingData.getLevel2Codes())) {
                            existingData.setLevel2Codes(pathInfo.getLevel2Code());
                        }
                        if (StringUtils.isEmpty(existingData.getLevel3Codes())) {
                            existingData.setLevel3Codes(level3Barcode.getBarcode());
                        }
                        hasValidChild = true;
                        log.debug("一级码{}已存在，跳过重复添加，但更新二三级码信息", level1Code);
                    }
                }

                if(codePathInfos.isEmpty()){
                    //说明只有三级码没有一级码 那么只需要导出三级码数据即可
                    String level3Key = "L3_" + level3Barcode.getBarcode(); // 使用特殊前缀避免与一级码冲突
                    if (!level1CodeMap.containsKey(level3Key)) {
                        BillsExportDto exportData = createExportDataForSingleCode(
                                bills, detail, "", "", level3Barcode.getBarcode(), ""
                        );
                        level1CodeMap.put(level3Key, exportData);
                        log.debug("添加三级码{}", level3Barcode.getBarcode());
                    }
                }
            }

            // 4. 处理更高级别码：递归查询到一级码，每个一级码一行（去重）
            for (Map.Entry<Integer, List<PdaMsfxBardata>> entry : levelGroups.entrySet()) {
                Integer level = entry.getKey();
                if (level !=1 && level !=2 && level !=3) {
                    List<PdaMsfxBardata> barcodes = entry.getValue();
                    for (PdaMsfxBardata barcode : barcodes) {
                        List<String> childLevel1Codes = getChildLevel1CodesRecursively(barcode.getBarcode(), level);
                        boolean hasValidChild = false;

                        for (String childCode : childLevel1Codes) {
                            if (!level1CodeMap.containsKey(childCode)) {
                                BillsExportDto exportData = createExportDataForSingleCode(
                                    bills, detail, childCode, "", "", level + "级:" + barcode.getBarcode()
                                );
                                level1CodeMap.put(childCode, exportData);
                                hasValidChild = true;
                                log.debug("添加{}级码{}的子码: {}", level, barcode.getBarcode(), childCode);
                            } else {
                                // 如果一级码已存在，更新其其他级别码信息（如果当前信息为空）
                                BillsExportDto existingData = level1CodeMap.get(childCode);
                                if (StringUtils.isEmpty(existingData.getOtherLevelCodes())) {
                                    existingData.setOtherLevelCodes(level + "级:" + barcode.getBarcode());
                                }
                                hasValidChild = true;
                                log.debug("一级码{}已存在，跳过重复添加，但更新{}级码信息", childCode, level);
                            }
                        }

                        if(childLevel1Codes.isEmpty()){
                            //说明只有高级码没有一级码 那么只需要导出高级码数据即可
                            String levelKey = "L" + level + "_" + barcode.getBarcode(); // 使用特殊前缀避免与一级码冲突
                            if (!level1CodeMap.containsKey(levelKey)) {
                                BillsExportDto exportData = createExportDataForSingleCode(
                                        bills, detail, "", "", "", barcode.getBarcode()
                                );
                                level1CodeMap.put(levelKey, exportData);
                                log.debug("添加{}级码{}", level, barcode.getBarcode());
                            }
                        }
                    }
                }
            }

            // 将去重后的数据添加到结果列表
            result.addAll(level1CodeMap.values());

            log.debug("单据{}药品{}创建导出数据完成，去重前可能有重复，去重后共{}行",
                bills.getBillsID(), detail.getDrugID(), result.size());

        } catch (Exception e) {
            log.error("为单据{}药品{}创建导出数据失败", bills.getBillsID(), detail.getDrugID(), e);
        }

        return result;
    }

    /**
     * 获取指定码的直接一级子码（不递归，去重处理）
     *
     * @param parentCode 父级码
     * @return 一级子码列表
     */
    private List<String> getChildLevel1Codes(String parentCode) {
        // 使用LinkedHashSet去重并保持插入顺序
        Set<String> resultSet = new LinkedHashSet<>();

        try {
            log.debug("查询码{}的直接一级子码", parentCode);

            // 查询BarRelation表获取子码
            List<BarRelation> relations = barRelationMapper.selectCurCodesByParentCodes(Arrays.asList(parentCode));

            if (relations != null && !relations.isEmpty()) {
                for (BarRelation relation : relations) {
                    String childCode = relation.getCurCode();
                    if (StringUtils.isNotEmpty(childCode)) {
                        try {
                            int childLevel = Integer.parseInt(relation.getCodeLevel());
                            if (childLevel == 1) {
                                if (resultSet.add(childCode)) {
                                    log.debug("找到一级子码: {}", childCode);
                                } else {
                                    log.debug("一级子码{}已存在，跳过重复添加", childCode);
                                }
                            }
                        } catch (NumberFormatException e) {
                            log.warn("解析码级别失败: {}", relation.getCodeLevel());
                        }
                    }
                }
            }

            log.debug("码{}的直接一级子码数量: {} (去重前: {})", parentCode, resultSet.size(),
                relations != null ? relations.size() : 0);

        } catch (Exception e) {
            log.error("查询码{}的直接一级子码失败", parentCode, e);
        }

        // 转换为List返回
        return new ArrayList<>(resultSet);
    }

    /**
     * 格式化日期字符串为 yyyy-MM-dd 格式（仅年月日）
     * 支持多种输入格式：yyyyMMdd、yyyy-MM-dd、yyyy-MM-dd HH:mm:ss等
     *
     * @param dateStr 原始日期字符串
     * @return 格式化后的日期字符串，格式为 yyyy-MM-dd，如果输入为空或格式错误则返回空字符串
     */
    private String formatDateString(String dateStr) {
        if (StringUtils.isEmpty(dateStr)) {
            return "";
        }

        try {
            // 尝试解析多种可能的日期格式
            DateTimeFormatter[] formatters = {
                DateTimeFormatter.ofPattern("yyyyMMdd"),                        // 20250427
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"),     // SQL Server datetime格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"),         // 毫秒格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),             // 标准格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"),                // 无秒格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd")                       // 仅日期格式
            };

            LocalDate date = null;
            for (DateTimeFormatter formatter : formatters) {
                try {
                    if (formatter.toString().contains("HH:mm")) {
                        // 包含时间的格式，先解析为LocalDateTime再转换为LocalDate
                        LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
                        date = dateTime.toLocalDate();
                    } else {
                        // 仅日期格式，直接解析为LocalDate
                        date = LocalDate.parse(dateStr, formatter);
                    }
                    break;
                } catch (Exception e) {
                    // 继续尝试下一个格式
                }
            }

            if (date != null) {
                // 格式化为 yyyy-MM-dd 格式
                return date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            } else {
                log.warn("无法解析日期格式: {}", dateStr);
                return ""; // 解析失败时返回空字符串
            }
        } catch (Exception e) {
            log.warn("日期格式化失败，原始日期: {}, 错误: {}", dateStr, e.getMessage());
            return ""; // 格式化失败时返回空字符串
        }
    }

    /**
     * 格式化确认时间用于导出
     * 将数据库中的确认时间格式化为标准的 yyyy-MM-dd HH:mm:ss 格式
     *
     * @param checkDate 原始确认时间字符串
     * @return 格式化后的确认时间字符串，格式为 yyyy-MM-dd HH:mm:ss
     */
    private String formatCheckDateForExport(String checkDate) {
        if (StringUtils.isEmpty(checkDate)) {
            return "";
        }

        try {
            // 尝试解析多种可能的日期时间格式
            DateTimeFormatter[] formatters = {
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS"), // SQL Server datetime格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"),     // 毫秒格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"),         // 标准格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"),            // 无秒格式
                DateTimeFormatter.ofPattern("yyyy-MM-dd")                   // 仅日期格式
            };

            LocalDateTime dateTime = null;
            for (DateTimeFormatter formatter : formatters) {
                try {
                    if (formatter.toString().contains("HH:mm")) {
                        dateTime = LocalDateTime.parse(checkDate, formatter);
                    } else {
                        // 仅日期格式，设置时间为00:00:00
                        LocalDate date = LocalDate.parse(checkDate, formatter);
                        dateTime = date.atStartOfDay();
                    }
                    break;
                } catch (Exception e) {
                    // 继续尝试下一个格式
                }
            }

            if (dateTime != null) {
                // 格式化为标准的 yyyy-MM-dd HH:mm:ss 格式
                return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            } else {
                log.warn("无法解析确认时间格式: {}", checkDate);
                return checkDate; // 解析失败时返回原字符串
            }
        } catch (Exception e) {
            log.warn("确认时间格式化失败，原始时间: {}, 错误: {}", checkDate, e.getMessage());
            return checkDate; // 格式化失败时返回原字符串
        }
    }

    /**
     * 码路径信息类，用于保存从高级码到一级码的路径
     */
    private static class CodePathInfo {
        private String level1Code;
        private String level2Code;

        public CodePathInfo(String level1Code, String level2Code) {
            this.level1Code = level1Code;
            this.level2Code = level2Code;
        }

        public String getLevel1Code() {
            return level1Code;
        }

        public String getLevel2Code() {
            return level2Code;
        }
    }

    /**
     * 递归获取指定码的所有一级子码，并保留路径信息（去重处理）
     *
     * @param parentCode 父级码
     * @param currentLevel 当前级别
     * @return 码路径信息列表
     */
    private List<CodePathInfo> getChildLevel1CodesWithPath(String parentCode, int currentLevel) {
        // 使用LinkedHashMap去重，以一级码为key，保持插入顺序
        Map<String, CodePathInfo> resultMap = new LinkedHashMap<>();

        try {
            log.debug("递归查询{}级码{}的所有一级子码（保留路径）", currentLevel, parentCode);

            // 查询BarRelation表获取子码
            List<BarRelation> relations = barRelationMapper.selectCurCodesByParentCodes(Arrays.asList(parentCode));

            if (relations != null && !relations.isEmpty()) {
                for (BarRelation relation : relations) {
                    String childCode = relation.getCurCode();
                    if (StringUtils.isNotEmpty(childCode)) {
                        try {
                            int childLevel = Integer.parseInt(relation.getCodeLevel());
                            if (childLevel == 1) {
                                // 找到一级码，根据当前级别决定二级码
                                String level2Code = (currentLevel == 3) ? "" : ""; // 三级码直接到一级码，二级码为空
                                if (!resultMap.containsKey(childCode)) {
                                    resultMap.put(childCode, new CodePathInfo(childCode, level2Code));
                                    log.debug("找到一级子码: {} (二级码: {})", childCode, level2Code);
                                } else {
                                    log.debug("一级子码{}已存在，跳过重复添加", childCode);
                                }
                            } else if (childLevel == 2 && currentLevel == 3) {
                                // 三级码到二级码，继续查询二级码的一级子码
                                List<String> level1Codes = getChildLevel1Codes(childCode);
                                for (String level1Code : level1Codes) {
                                    if (!resultMap.containsKey(level1Code)) {
                                        resultMap.put(level1Code, new CodePathInfo(level1Code, childCode));
                                        log.debug("找到一级子码: {} (经过二级码: {})", level1Code, childCode);
                                    } else {
                                        log.debug("一级子码{}已存在，跳过重复添加", level1Code);
                                    }
                                }
                            } else if (childLevel > 1) {
                                // 还不是一级码或二级码，继续递归
                                List<CodePathInfo> subResult = getChildLevel1CodesWithPath(childCode, childLevel);
                                int beforeSize = resultMap.size();
                                for (CodePathInfo pathInfo : subResult) {
                                    resultMap.putIfAbsent(pathInfo.getLevel1Code(), pathInfo);
                                }
                                int addedCount = resultMap.size() - beforeSize;
                                log.debug("从{}级码{}递归得到{}个一级码，实际新增{}个",
                                    childLevel, childCode, subResult.size(), addedCount);
                            }
                        } catch (NumberFormatException e) {
                            log.warn("解析码级别失败: {}", relation.getCodeLevel());
                        }
                    }
                }
            }

            log.debug("{}级码{}递归查询完成，共找到{}个一级子码（去重后）", currentLevel, parentCode, resultMap.size());

        } catch (Exception e) {
            log.error("递归查询{}级码{}的一级子码失败", currentLevel, parentCode, e);
        }

        // 转换为List返回
        return new ArrayList<>(resultMap.values());
    }

    /**
     * 递归获取指定码的所有一级子码（去重处理）
     *
     * @param parentCode 父级码
     * @param currentLevel 当前级别
     * @return 一级子码列表
     */
    private List<String> getChildLevel1CodesRecursively(String parentCode, int currentLevel) {
        // 使用LinkedHashSet去重并保持插入顺序
        Set<String> resultSet = new LinkedHashSet<>();

        try {
            log.debug("递归查询{}级码{}的所有一级子码", currentLevel, parentCode);

            // 查询BarRelation表获取子码
            List<BarRelation> relations = barRelationMapper.selectCurCodesByParentCodes(Arrays.asList(parentCode));

            if (relations != null && !relations.isEmpty()) {
                for (BarRelation relation : relations) {
                    String childCode = relation.getCurCode();
                    if (StringUtils.isNotEmpty(childCode)) {
                        try {
                            int childLevel = Integer.parseInt(relation.getCodeLevel());
                            if (childLevel == 1) {
                                // 找到一级码，直接添加（自动去重）
                                if (resultSet.add(childCode)) {
                                    log.debug("找到一级子码: {}", childCode);
                                } else {
                                    log.debug("一级子码{}已存在，跳过重复添加", childCode);
                                }
                            } else if (childLevel > 1) {
                                // 还不是一级码，继续递归
                                List<String> subResult = getChildLevel1CodesRecursively(childCode, childLevel);
                                int beforeSize = resultSet.size();
                                resultSet.addAll(subResult);
                                int addedCount = resultSet.size() - beforeSize;
                                log.debug("从{}级码{}递归得到{}个一级码，实际新增{}个",
                                    childLevel, childCode, subResult.size(), addedCount);
                            }
                        } catch (NumberFormatException e) {
                            log.warn("解析码级别失败: {}", relation.getCodeLevel());
                        }
                    }
                }
            }

            log.debug("{}级码{}递归查询完成，共找到{}个一级子码（去重后）", currentLevel, parentCode, resultSet.size());

        } catch (Exception e) {
            log.error("递归查询{}级码{}的一级子码失败", currentLevel, parentCode, e);
        }

        // 转换为List返回
        return new ArrayList<>(resultSet);
    }

    /**
     * 创建单个码的导出数据对象
     */
    private BillsExportDto createExportDataForSingleCode(PdaBillsList bills, PdaWarehouseBillsDetail detail,
                                                        String level1Code, String level2Code, String level3Code, String otherLevelCode) {
        BillsExportDto exportData = new BillsExportDto();

        // 单据主表信息
        exportData.setBillsID(bills.getBillsID());
        exportData.setBillsCD(bills.getBillsCD());
        exportData.setCheckDate(formatCheckDateForExport(bills.getCheckDate()));

        // 明细信息（如果有）
        if (detail != null) {
            exportData.setDrugID(detail.getDrugID());
            exportData.setDrugName(detail.getDrugName());
            exportData.setDrugGG(detail.getDrugGG());
            exportData.setDrugDW(detail.getDrugDW());
            exportData.setDrugNum(detail.getDrugNum());
            exportData.setDrugCheckNum(detail.getDrugCheckNum());
            exportData.setDrugCD(detail.getDrugCD());
            //编码为一级码的前七位
            if(StringUtils.isNotEmpty(level1Code) && level1Code.length() >= 7){
                exportData.setDrugCode(level1Code.substring(0, 7));
            }
            exportData.setDrugBatchNo(detail.getDrugBatchNo());
            exportData.setDrugPD(formatDateString(detail.getDrugPD()));
            exportData.setDrugExp(formatDateString(detail.getDrugExp()));
            exportData.setRemarks(detail.getRemarks1());
        }

        // 码信息（不使用逗号拼接，每个码单独显示）
        exportData.setLevel1Codes(level1Code != null ? level1Code : "");
        exportData.setLevel2Codes(level2Code != null ? level2Code : "");
        exportData.setLevel3Codes(level3Code != null ? level3Code : "");
        exportData.setOtherLevelCodes(otherLevelCode != null ? otherLevelCode : "");

        return exportData;
    }

    /**
     * 获取单据明细列表（用于批次号维护）
     *
     * @param billsID 单据号
     * @return 明细列表
     */
    @Override
    public List<Map<String, Object>> selectBillsDetailList(String billsID) {
        try {
            log.info("查询单据明细列表，单据号: {}", billsID);
            
            // 查询单据明细
            List<PdaWarehouseBillsDetail> detailList = pdaBillsListMapper.selectPdaWarehouseBillsDetailByBillsID(billsID);
            
            List<Map<String, Object>> result = new ArrayList<>();
            
            for (PdaWarehouseBillsDetail detail : detailList) {
                Map<String, Object> detailMap = new HashMap<>();
                detailMap.put("detailID", detail.getBillsID() + "_" + detail.getDrugID()); // 使用组合键作为明细ID
                detailMap.put("drugID", detail.getDrugID());
                detailMap.put("drugName", detail.getDrugName());
                detailMap.put("specification", detail.getDrugGG());
                detailMap.put("unit", detail.getDrugDW());
                detailMap.put("quantity", detail.getDrugNum());
                detailMap.put("batchNumber", detail.getDrugBatchNo());
                detailMap.put("drugCD", detail.getDrugCD());
                detailMap.put("drugBH", detail.getDrugBH());
                detailMap.put("drugPD", detail.getDrugPD());
                detailMap.put("drugExp", detail.getDrugExp());
                detailMap.put("remarks", detail.getRemarks());
                
                result.add(detailMap);
            }
            
            log.info("查询单据明细列表完成，单据号: {}，明细数量: {}", billsID, result.size());
            return result;
            
        } catch (Exception e) {
            log.error("查询单据明细列表失败，单据号: {}", billsID, e);
            throw new RuntimeException("查询单据明细列表失败", e);
        }
    }

    /**
     * 更新明细批次号
     *
     * @param billsID 单据号
     * @param details 明细数据列表
     * @return 更新结果
     */
    @Override
    @Transactional
    public int updateDetailBatchNumber(String billsID, List<Map<String, Object>> details) {
        try {
            log.info("开始更新明细批次号，单据号: {}，明细数量: {}", billsID, details.size());
            
            int updateCount = 0;
            
            for (Map<String, Object> detail : details) {
                String drugID = (String) detail.get("drugID");
                String drugName = (String) detail.get("drugName");
                String batchNumber = (String) detail.get("batchNumber");
                String drugPD = (String) detail.get("drugPD");
                String drugExp = (String) detail.get("drugExp");
                String remark = (String) detail.get("remark");
                
                if (StringUtils.isNotEmpty(drugID)) {
                    // 构建更新对象
                    PdaWarehouseBillsDetail updateDetail = new PdaWarehouseBillsDetail();
                    updateDetail.setBillsID(billsID);
                    updateDetail.setDrugID(drugID);
                    updateDetail.setDrugName(drugName);
                    updateDetail.setDrugBatchNo(batchNumber);
                    updateDetail.setDrugPD(drugPD);
                    updateDetail.setDrugExp(drugExp);
                    updateDetail.setRemarks(remark);
                    
                    // 执行更新
                    int result = pdaBillsListMapper.updatePdaWarehouseBillsDetail(updateDetail);
                    if (result > 0) {
                        updateCount++;
                        log.debug("更新明细成功，药品ID: {}，批次号: {}，生产日期: {}，有效期: {}", drugID, batchNumber, drugPD, drugExp);
                    } else {
                        log.warn("更新明细失败，药品ID: {}", drugID);
                    }
                }
            }
            
            log.info("批次号维护完成，单据号: {}，成功更新: {} 条", billsID, updateCount);
            return updateCount;
            
        } catch (Exception e) {
            log.error("批次号维护失败，单据号: {}", billsID, e);
            throw new RuntimeException("批次号维护失败", e);
        }
    }

    /**
     * 通过单据号导入数据
     *
     * @param billsID 单据号
     * @return 导入结果
     */
    @Override
    public Map<String, Object> importBillsByBillsID(String billsID) {
        Map<String, Object> result = new HashMap<>();

        try {
            log.info("开始通过单据号导入数据，单据号: {}", billsID);

            // 调用SOAP接口QueryBillsDetail，接口会自动将数据保存到数据库
            String soapResponse = callQueryBillsDetailSoap(billsID);

            if (StringUtils.isEmpty(soapResponse)) {
                result.put("success", false);
                result.put("message", "调用SOAP接口失败，未获取到数据");
                return result;
            }

            // 检查SOAP响应中的业务结果
            Map<String, Object> businessResult = checkSoapBusinessResult(soapResponse, "QueryBillsDetailResult");

            if ((Boolean) businessResult.get("success")) {
                result.put("success", true);
                result.put("message", "单据导入成功，单据号: " + billsID);
                result.put("billsID", billsID);
                log.info("单据号导入完成，单据号: {}", billsID);
            } else {
                result.put("success", false);
                result.put("message", "单据导入失败: " + businessResult.get("message"));
                log.error("单据号导入失败，单据号: {}，错误信息: {}", billsID, businessResult.get("message"));
            }

        } catch (Exception e) {
            log.error("单据号导入失败，单据号: {}", billsID, e);
            result.put("success", false);
            result.put("message", "导入失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 通过单据号和单据时间导入数据（使用QueryBillsDetailToSQL接口）
     *
     * @param billsID 单据号
     * @param billsTime 单据时间
     * @return 导入结果
     */
    public Map<String, Object> importBillsByBillsIDAndTime(String billsID, String billsTime) {
        Map<String, Object> result = new HashMap<>();

        try {
            log.info("开始通过单据号和时间导入数据，单据号: {}，时间: {}", billsID, billsTime);

            // 调用SOAP接口QueryBillsDetailToSQL，接口会自动将数据保存到数据库
            String soapResponse = callQueryBillsDetailToSQLSoap(billsID, billsTime);

            if (StringUtils.isEmpty(soapResponse)) {
                result.put("success", false);
                result.put("message", "调用SOAP接口失败，未获取到数据");
                return result;
            }

            // 检查SOAP响应中的业务结果
            Map<String, Object> businessResult = checkSoapBusinessResult(soapResponse, "QueryBillsDetailToSQLResult");

            if ((Boolean) businessResult.get("success")) {
                result.put("success", true);
                result.put("message", "单据导入成功，单据号: " + billsID);
                result.put("billsID", billsID);
                result.put("billsTime", billsTime);
                log.info("单据号和时间导入完成，单据号: {}，时间: {}", billsID, billsTime);
            } else {
                result.put("success", false);
                result.put("message", "单据导入失败: " + businessResult.get("message"));
                log.error("单据号和时间导入失败，单据号: {}，时间: {}，错误信息: {}", billsID, billsTime, businessResult.get("message"));
            }

        } catch (Exception e) {
            log.error("单据号和时间导入失败，单据号: {}，时间: {}", billsID, billsTime, e);
            result.put("success", false);
            result.put("message", "导入失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 通过时间段查询单据列表（不直接导入，返回单据列表供用户选择）
     *
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param institutionName 往来单位名称（可选）
     * @param billsType 单据类型（A-全部，AI-入库，AO-出库）
     * @return 查询结果，包含单据列表
     */
    @Override
    public Map<String, Object> importBillsByDateRange(String startDate, String endDate, String institutionName, String billsType) {
        Map<String, Object> result = new HashMap<>();

        try {
            log.info("开始通过时间段查询单据列表，时间范围: {} 到 {}，往来单位: {}，单据类型: {}", startDate, endDate, institutionName, billsType);

            // 调用SOAP接口QueryWareHouseBills，获取单据列表
            String soapResponse = callQueryWareHouseBillsSoap(startDate, endDate, institutionName, billsType);

            if (StringUtils.isEmpty(soapResponse)) {
                result.put("success", false);
                result.put("message", "调用SOAP接口失败，未获取到数据");
                return result;
            }

            // 首先检查SOAP响应中的业务结果
            Map<String, Object> businessResult = checkSoapBusinessResult(soapResponse, "QueryWareHouseBillsResult");

            if (!(Boolean) businessResult.get("success")) {
                result.put("success", false);
                result.put("message", "查询失败: " + businessResult.get("message"));
                return result;
            }

            // 解析SOAP响应，提取单据列表
            Map<String, Object> parseResult = parseBillsListFromResponse(soapResponse);
            List<Map<String, Object>> billsList = (List<Map<String, Object>>) parseResult.get("billsList");
            int totalNum = (Integer) parseResult.get("totalNum");

            if (billsList.isEmpty()) {
                result.put("success", true);
                result.put("message", "查询成功，但未找到符合条件的单据");
                result.put("billsList", billsList);
                result.put("currentPageCount", 0);
                result.put("totalCount", totalNum);
            } else {
                result.put("success", true);
                result.put("message", String.format("查询成功，当前页找到 %d 条单据，总共 %d 条", billsList.size(), totalNum));
                result.put("billsList", billsList);
                result.put("currentPageCount", billsList.size());
                result.put("totalCount", totalNum);
            }

            log.info("时间段查询完成，时间范围: {} 到 {}，找到 {} 条单据", startDate, endDate, billsList.size());

        } catch (Exception e) {
            log.error("时间段查询失败，时间范围: {} 到 {}", startDate, endDate, e);
            result.put("success", false);
            result.put("message", "查询失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 调用QueryBillsDetail SOAP接口
     *
     * @param billsID 单据号
     * @return SOAP响应
     */
    private String callQueryBillsDetailSoap(String billsID) {
        try {
            log.info("调用QueryBillsDetail SOAP接口，单据号: {}", billsID);

            // 构建SOAP请求体
            String soapBody = buildQueryBillsDetailSoapRequest(billsID);
            log.debug("QueryBillsDetail SOAP请求体: {}", soapBody);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_XML);
            headers.set("SOAPAction", "http://tempuri.org/QueryBillsDetail");

            HttpEntity<String> entity = new HttpEntity<>(soapBody, headers);

            // 发送请求
            ResponseEntity<String> response = restTemplate.postForEntity(SOAP_URL, entity, String.class);

            log.info("QueryBillsDetail SOAP响应状态: {}", response.getStatusCode());
            log.debug("QueryBillsDetail SOAP响应内容: {}", response.getBody());

            if (response.getStatusCode() == HttpStatus.OK && StringUtils.isNotEmpty(response.getBody())) {
                return response.getBody();
            } else {
                log.error("QueryBillsDetail SOAP接口调用失败，状态码: {}", response.getStatusCode());
                return null;
            }

        } catch (Exception e) {
            log.error("调用QueryBillsDetail SOAP接口异常", e);
            return null;
        }
    }

    /**
     * 调用QueryBillsDetailToSQL SOAP接口
     *
     * @param billsID 单据号
     * @param billsTime 单据时间
     * @return SOAP响应
     */
    private String callQueryBillsDetailToSQLSoap(String billsID, String billsTime) {
        try {
            log.info("调用QueryBillsDetailToSQL SOAP接口，单据号: {}，时间: {}", billsID, billsTime);

            // 构建SOAP请求体
            String soapBody = buildQueryBillsDetailToSQLSoapRequest(billsID, billsTime);
            log.debug("QueryBillsDetailToSQL SOAP请求体: {}", soapBody);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_XML);
            headers.set("SOAPAction", "http://tempuri.org/QueryBillsDetailToSQL");

            HttpEntity<String> entity = new HttpEntity<>(soapBody, headers);

            // 发送请求
            ResponseEntity<String> response = restTemplate.postForEntity(SOAP_URL, entity, String.class);

            log.info("QueryBillsDetailToSQL SOAP响应状态: {}", response.getStatusCode());
            log.debug("QueryBillsDetailToSQL SOAP响应内容: {}", response.getBody());

            if (response.getStatusCode() == HttpStatus.OK && StringUtils.isNotEmpty(response.getBody())) {
                return response.getBody();
            } else {
                log.error("QueryBillsDetailToSQL SOAP接口调用失败，状态码: {}", response.getStatusCode());
                return null;
            }

        } catch (Exception e) {
            log.error("调用QueryBillsDetailToSQL SOAP接口异常", e);
            return null;
        }
    }

    /**
     * 调用QueryWareHouseBills SOAP接口
     *
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param institutionName 往来单位名称
     * @param billsType 单据类型
     * @return SOAP响应
     */
    private String callQueryWareHouseBillsSoap(String startDate, String endDate, String institutionName, String billsType) {
        try {
            log.info("调用QueryWareHouseBills SOAP接口，时间范围: {} 到 {}，往来单位: {}，单据类型: {}", startDate, endDate, institutionName, billsType);

            // 构建SOAP请求体
            String soapBody = buildQueryWareHouseBillsSoapRequest(startDate, endDate, institutionName, billsType);
            log.debug("QueryWareHouseBills SOAP请求体: {}", soapBody);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_XML);
            headers.set("SOAPAction", "http://tempuri.org/QueryWareHouseBills");

            HttpEntity<String> entity = new HttpEntity<>(soapBody, headers);

            // 发送请求
            ResponseEntity<String> response = restTemplate.postForEntity(SOAP_URL, entity, String.class);

            log.info("QueryWareHouseBills SOAP响应状态: {}", response.getStatusCode());
            log.debug("QueryWareHouseBills SOAP响应内容: {}", response.getBody());

            if (response.getStatusCode() == HttpStatus.OK && StringUtils.isNotEmpty(response.getBody())) {
                return response.getBody();
            } else {
                log.error("QueryWareHouseBills SOAP接口调用失败，状态码: {}", response.getStatusCode());
                return null;
            }

        } catch (Exception e) {
            log.error("调用QueryWareHouseBills SOAP接口异常", e);
            return null;
        }
    }

    /**
     * 构建QueryBillsDetail SOAP请求体
     *
     * @param billsID 单据号
     * @return SOAP请求体
     */
    private String buildQueryBillsDetailSoapRequest(String billsID) {
        StringBuilder soap = new StringBuilder();
        soap.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        soap.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
        soap.append("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
        soap.append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
        soap.append("<soap:Body>");
        soap.append("<QueryBillsDetail xmlns=\"http://tempuri.org/\">");
        soap.append("<BillsID>").append(billsID).append("</BillsID>");
        soap.append("</QueryBillsDetail>");
        soap.append("</soap:Body>");
        soap.append("</soap:Envelope>");

        return soap.toString();
    }

    /**
     * 构建QueryBillsDetailToSQL SOAP请求体
     *
     * @param billsID 单据号
     * @param billsTime 单据时间
     * @return SOAP请求体
     */
    private String buildQueryBillsDetailToSQLSoapRequest(String billsID, String billsTime) {
        StringBuilder soap = new StringBuilder();
        soap.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        soap.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
        soap.append("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
        soap.append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
        soap.append("<soap:Body>");
        soap.append("<QueryBillsDetailToSQL xmlns=\"http://tempuri.org/\">");
        soap.append("<BillsID>").append(billsID).append("</BillsID>");
        soap.append("<BillsTime>").append(billsTime).append("</BillsTime>");
        soap.append("</QueryBillsDetailToSQL>");
        soap.append("</soap:Body>");
        soap.append("</soap:Envelope>");

        return soap.toString();
    }

    /**
     * 构建QueryWareHouseBills SOAP请求体
     *
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @param institutionName 往来单位名称
     * @param billsType 单据类型（A-全部，AI-入库，AO-出库）
     * @return SOAP请求体
     */
    private String buildQueryWareHouseBillsSoapRequest(String startDate, String endDate, String institutionName, String billsType) {
        StringBuilder soap = new StringBuilder();
        soap.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        soap.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
        soap.append("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
        soap.append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
        soap.append("<soap:Body>");
        soap.append("<QueryWareHouseBills xmlns=\"http://tempuri.org/\">");
        soap.append("<BeginDate>").append(startDate).append("</BeginDate>");
        soap.append("<EndDate>").append(endDate).append("</EndDate>");
        soap.append("<billsType>").append(StringUtils.isNotEmpty(billsType) ? billsType : "AO").append("</billsType>"); // 使用传入的单据类型，默认为出库
        soap.append("<bussinessrefID>").append(StringUtils.isNotEmpty(institutionName) ? institutionName : "").append("</bussinessrefID>");
        soap.append("<page>").append("1").append("</page>");
        soap.append("</QueryWareHouseBills>");
        soap.append("</soap:Body>");
        soap.append("</soap:Envelope>");

        return soap.toString();
    }



    /**
     * 获取所有往来单位列表（前端过滤）
     *
     * @return 往来单位列表
     */
    @Override
    public List<Map<String, Object>> getAllInstitutionsList() {
        List<Map<String, Object>> institutions = new ArrayList<>();

        try {
            log.info("查询所有往来单位列表");

            // 从PDA_Msfx_Customer表查询所有往来单位
            institutions = pdaMsfxCustomerMapper.selectCustomerListByKeyword(null);

            log.info("查询到往来单位数量: {}", institutions.size());

        } catch (Exception e) {
            log.error("查询往来单位列表异常", e);
        }

        return institutions;
    }

    /**
     * 更新往来单位信息
     *
     * @return 更新结果
     */
    @Override
    public Map<String, Object> updateCustomerInfo() {
        Map<String, Object> result = new HashMap<>();

        try {
            log.info("开始更新往来单位信息");

            // 调用GetCustomerToSQL SOAP接口，接口会自动将数据保存到数据库
            // 只调用第一页，让SOAP接口处理所有数据
            String soapResponse = callGetCustomerToSQLSoap(1);

            if (StringUtils.isEmpty(soapResponse)) {
                result.put("success", false);
                result.put("message", "调用SOAP接口失败，未获取到数据");
                return result;
            }

            // 检查SOAP响应中的业务结果
            Map<String, Object> businessResult = checkSoapBusinessResult(soapResponse, "GetCustomerToSQLResult");

            if ((Boolean) businessResult.get("success")) {
                result.put("success", true);
                result.put("message", "往来单位信息更新成功");
                log.info("往来单位信息更新完成");
            } else {
                result.put("success", false);
                result.put("message", "往来单位信息更新失败: " + businessResult.get("message"));
                log.error("往来单位信息更新失败，错误信息: {}", businessResult.get("message"));
            }

        } catch (Exception e) {
            log.error("更新往来单位信息失败", e);
            result.put("success", false);
            result.put("message", "更新失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 调用GetCustomerToSQL SOAP接口
     *
     * @param page 页码
     * @return SOAP响应
     */
    private String callGetCustomerToSQLSoap(int page) {
        try {
            log.info("调用GetCustomerToSQL SOAP接口，页码: {}", page);

            // 构建SOAP请求体
            String soapBody = buildGetCustomerToSQLSoapRequest(page);
            log.debug("GetCustomerToSQL SOAP请求体: {}", soapBody);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_XML);
            headers.set("SOAPAction", "http://tempuri.org/GetCustomerToSQL");

            HttpEntity<String> entity = new HttpEntity<>(soapBody, headers);

            // 发送请求
            ResponseEntity<String> response = restTemplate.postForEntity(SOAP_URL, entity, String.class);

            log.info("GetCustomerToSQL SOAP响应状态: {}", response.getStatusCode());
            log.debug("GetCustomerToSQL SOAP响应内容: {}", response.getBody());

            if (response.getStatusCode() == HttpStatus.OK && StringUtils.isNotEmpty(response.getBody())) {
                return response.getBody();
            } else {
                log.error("GetCustomerToSQL SOAP接口调用失败，状态码: {}", response.getStatusCode());
                return null;
            }

        } catch (Exception e) {
            log.error("调用GetCustomerToSQL SOAP接口异常，页码: {}", page, e);
            return null;
        }
    }

    /**
     * 构建GetCustomerToSQL SOAP请求体
     *
     * @param page 页码
     * @return SOAP请求体
     */
    private String buildGetCustomerToSQLSoapRequest(int page) {
        StringBuilder soap = new StringBuilder();
        soap.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        soap.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
        soap.append("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
        soap.append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
        soap.append("<soap:Body>");
        soap.append("<GetCustomerToSQL xmlns=\"http://tempuri.org/\">");
        soap.append("<EntID>").append("111").append("</EntID>");
        soap.append("<page>").append(page).append("</page>");
        soap.append("</GetCustomerToSQL>");
        soap.append("</soap:Body>");
        soap.append("</soap:Envelope>");

        return soap.toString();
    }



    /**
     * 定时查询当天出库单据
     *
     * @return 查询结果
     */
    @Override
    public Map<String, Object> queryTodayOutboundBills(String billsType) {
        Map<String, Object> result = new HashMap<>();

        try {
            // 获取当天日期和明天日期，格式为yyyyMMdd
            String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            String tomorrow = LocalDate.now().plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

            log.info("开始定时查询当天出库单据，查询范围: {} 到 {}", today, tomorrow);

            // 调用SOAP接口QueryWareHouseBillsToSQL，接口会自动将数据保存到数据库
            // 使用今天作为开始时间，明天作为结束时间，确保覆盖当天所有数据
            String soapResponse = callQueryWareHouseBillsToSQLSoap(today, tomorrow, billsType, 1);

            if (StringUtils.isEmpty(soapResponse)) {
                result.put("success", false);
                result.put("message", "调用SOAP接口失败，未获取到数据");
                return result;
            }

            // SOAP接口调用成功，数据已自动保存到数据库
            result.put("success", true);
            result.put("message", "当天出库单据查询成功，查询范围: " + today + " 到 " + tomorrow);
            result.put("queryDate", today);
            result.put("queryRange", today + " 到 " + tomorrow);
            log.info("当天出库单据查询完成，查询范围: {} 到 {}", today, tomorrow);

        } catch (Exception e) {
            log.error("定时查询当天出库单据失败", e);
            result.put("success", false);
            result.put("message", "查询失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 调用QueryWareHouseBillsToSQL SOAP接口
     *
     * @param beginDate 开始日期
     * @param endDate 结束日期
     * @param billsType 单据类型
     * @param page 页码
     * @return SOAP响应
     */
    private String callQueryWareHouseBillsToSQLSoap(String beginDate, String endDate, String billsType, int page) {
        try {
            log.info("调用QueryWareHouseBillsToSQL SOAP接口，时间范围: {} 到 {}，单据类型: {}，页码: {}",
                beginDate, endDate, billsType, page);

            // 构建SOAP请求体
            String soapBody = buildQueryWareHouseBillsToSQLSoapRequest(beginDate, endDate, billsType, page);
            log.debug("QueryWareHouseBillsToSQL SOAP请求体: {}", soapBody);

            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_XML);
            headers.set("SOAPAction", "http://tempuri.org/QueryWareHouseBillsToSQL");

            HttpEntity<String> entity = new HttpEntity<>(soapBody, headers);

            // 发送请求
            ResponseEntity<String> response = restTemplate.postForEntity(SOAP_URL, entity, String.class);

            log.info("QueryWareHouseBillsToSQL SOAP响应状态: {}", response.getStatusCode());
            log.debug("QueryWareHouseBillsToSQL SOAP响应内容: {}", response.getBody());

            if (response.getStatusCode() == HttpStatus.OK && StringUtils.isNotEmpty(response.getBody())) {
                return response.getBody();
            } else {
                log.error("QueryWareHouseBillsToSQL SOAP接口调用失败，状态码: {}", response.getStatusCode());
                return null;
            }

        } catch (Exception e) {
            log.error("调用QueryWareHouseBillsToSQL SOAP接口异常", e);
            return null;
        }
    }

    /**
     * 构建QueryWareHouseBillsToSQL SOAP请求体
     *
     * @param beginDate 开始日期
     * @param endDate 结束日期
     * @param billsType 单据类型
     * @param page 页码
     * @return SOAP请求体
     */
    private String buildQueryWareHouseBillsToSQLSoapRequest(String beginDate, String endDate, String billsType, int page) {
        StringBuilder soap = new StringBuilder();
        soap.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
        soap.append("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ");
        soap.append("xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" ");
        soap.append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
        soap.append("<soap:Body>");
        soap.append("<QueryWareHouseBillsToSQL xmlns=\"http://tempuri.org/\">");
        soap.append("<BeginDate>").append(beginDate).append("</BeginDate>");
        soap.append("<EndDate>").append(endDate).append("</EndDate>");
        soap.append("<billsType>").append(billsType).append("</billsType>");
        soap.append("<page>").append(page).append("</page>");
        soap.append("</QueryWareHouseBillsToSQL>");
        soap.append("</soap:Body>");
        soap.append("</soap:Envelope>");

        return soap.toString();
    }

    /**
     * 解析SOAP响应中的单据列表
     *
     * @param soapResponse SOAP响应
     * @return 包含单据列表和总数的结果
     */
    private Map<String, Object> parseBillsListFromResponse(String soapResponse) {
        Map<String, Object> result = new HashMap<>();
        List<Map<String, Object>> billsList = new ArrayList<>();
        int totalNum = 0;

        try {
            log.info("开始解析SOAP响应中的单据列表");

            // 提取JSON字符串（去掉SOAP包装）
            String jsonString = extractJsonFromSoapResponse(soapResponse);
            if (StringUtils.isEmpty(jsonString)) {
                log.warn("未能从SOAP响应中提取JSON数据");
                result.put("billsList", billsList);
                result.put("totalNum", totalNum);
                return result;
            }

            // 解析JSON
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(jsonString);

            // 导航到单据列表节点
            JsonNode resultNode = rootNode
                .path("alibaba_alihealth_drug_kyt_wes_searchbill_response")
                .path("result")
                .path("model");

            JsonNode billListNode = resultNode
                .path("result_list")
                .path("bill_chk_in_out_do");

            // 获取总数
            totalNum = resultNode.path("total_num").asInt(0);
            log.info("API返回总数: {}", totalNum);

            if (billListNode.isArray()) {
                for (JsonNode billNode : billListNode) {
                    Map<String, Object> billInfo = new HashMap<>();
                    billInfo.put("billCode", billNode.path("bill_code").asText(""));
                    billInfo.put("billId", billNode.path("bill_id").asText(""));
                    billInfo.put("billTime", billNode.path("bill_time").asText(""));
                    billInfo.put("billType", billNode.path("bill_type").asText(""));
                    billInfo.put("billTypeName", billNode.path("bill_type_name").asText(""));
                    billInfo.put("fromUserName", billNode.path("from_user_name").asText(""));
                    billInfo.put("toUserName", billNode.path("to_user_name").asText(""));
                    billInfo.put("processDate", billNode.path("process_date").asText(""));
                    billInfo.put("uploadFileName", billNode.path("upload_file_name").asText(""));
                    billInfo.put("fromRefUserId", billNode.path("from_ref_user_id").asText(""));
                    billInfo.put("toRefUserId", billNode.path("to_ref_user_id").asText(""));

                    billsList.add(billInfo);
                }
            }

            log.info("解析完成，当前页找到 {} 条单据，总数: {}", billsList.size(), totalNum);

        } catch (Exception e) {
            log.error("解析SOAP响应中的单据列表失败", e);
        }

        result.put("billsList", billsList);
        result.put("totalNum", totalNum);
        return result;
    }

    /**
     * 从SOAP响应中提取JSON字符串
     *
     * @param soapResponse SOAP响应
     * @return JSON字符串
     */
    private String extractJsonFromSoapResponse(String soapResponse) {
        try {
            // 查找<QueryWareHouseBillsResult>标签中的内容
            String startTag = "<QueryWareHouseBillsResult>";
            String endTag = "</QueryWareHouseBillsResult>";

            int startIndex = soapResponse.indexOf(startTag);
            if (startIndex == -1) {
                log.warn("未找到QueryWareHouseBillsResult开始标签");
                return null;
            }

            int contentStart = startIndex + startTag.length();
            int contentEnd = soapResponse.indexOf(endTag, contentStart);

            if (contentEnd > contentStart) {
                String jsonString = soapResponse.substring(contentStart, contentEnd);
                return jsonString.trim();
            } else {
                log.warn("未找到QueryWareHouseBillsResult结束标签");
            }
        } catch (Exception e) {
            log.error("从SOAP响应中提取JSON字符串失败", e);
        }

        return null;
    }

    /**
     * 批量导入选中的单据
     *
     * @param billsData 选中的单据数据列表（包含单据号和单据时间）
     * @return 导入结果
     */
    @Override
    public Map<String, Object> importSelectedBills(List<Map<String, String>> billsData) {
        Map<String, Object> result = new HashMap<>();

        try {
            log.info("开始批量导入选中的单据，单据数量: {}", billsData.size());

            int successCount = 0;
            int failCount = 0;
            List<String> failedBills = new ArrayList<>();

            for (Map<String, String> billData : billsData) {
                String billCode = billData.get("billCode");
                String billTime = billData.get("billTime");

                try {
                    log.info("正在导入单据: {}，时间: {}", billCode, billTime);

                    // 调用新的单据号和时间导入方法
                    Map<String, Object> importResult = importBillsByBillsIDAndTime(billCode, billTime);

                    if ((Boolean) importResult.get("success")) {
                        successCount++;
                        log.info("单据 {} 导入成功", billCode);
                    } else {
                        failCount++;
                        failedBills.add(billCode);
                        log.error("单据 {} 导入失败: {}", billCode, importResult.get("message"));
                    }

                } catch (Exception e) {
                    failCount++;
                    failedBills.add(billCode);
                    log.error("导入单据 {} 时发生异常", billCode, e);
                }

                // 为了避免频繁调用接口，每次导入后稍作延迟
                try {
                    Thread.sleep(500); // 延迟0.5秒
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.warn("批量导入任务被中断");
                    break;
                }
            }

            result.put("success", true);
            result.put("message", String.format("批量导入完成，成功 %d 条，失败 %d 条", successCount, failCount));
            result.put("totalCount", billsData.size());
            result.put("successCount", successCount);
            result.put("failCount", failCount);
            result.put("failedBills", failedBills);

            log.info("批量导入完成，总数: {}，成功: {}，失败: {}", billsData.size(), successCount, failCount);

        } catch (Exception e) {
            log.error("批量导入选中单据失败", e);
            result.put("success", false);
            result.put("message", "批量导入失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 检查SOAP响应中的业务结果
     *
     * @param soapResponse SOAP响应
     * @param resultTagName 结果标签名称
     * @return 业务结果
     */
    private Map<String, Object> checkSoapBusinessResult(String soapResponse, String resultTagName) {
        Map<String, Object> result = new HashMap<>();

        try {
            log.debug("开始检查SOAP业务结果，标签名: {}", resultTagName);

            // 提取JSON字符串
            String jsonString = extractJsonFromSoapResult(soapResponse, resultTagName);
            if (StringUtils.isEmpty(jsonString)) {
                result.put("success", false);
                result.put("message", "无法从SOAP响应中提取业务结果");
                return result;
            }

            log.debug("提取的JSON内容: {}", jsonString);

            // 解析JSON
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode rootNode = objectMapper.readTree(jsonString);

            // 检查业务成功标志
            // 对于时间段查询，检查嵌套的success字段
            JsonNode nestedResult = rootNode.path("alibaba_alihealth_drug_kyt_wes_searchbill_response").path("result");
            boolean nestedSuccess = nestedResult.path("success").asBoolean(false);
            String nestedMsgCode = nestedResult.path("msg_code").asText("");
            String nestedMsgInfo = nestedResult.path("msg_info").asText("");

            // 检查直接的success字段
            boolean responseSuccess = rootNode.path("response_success").asBoolean(true); // 默认为true，兼容没有此字段的情况
            String msgCode = rootNode.path("msg_code").asText("");
            String msgInfo = rootNode.path("msg_info").asText("");

            // 优先检查嵌套结构（时间段查询）
            if (nestedResult.isMissingNode()) {
                // 没有嵌套结构，使用直接字段
                if (responseSuccess && !"ERROR".equals(msgCode)) {
                    result.put("success", true);
                    result.put("message", StringUtils.isNotEmpty(msgInfo) ? msgInfo : "操作成功");
                } else {
                    result.put("success", false);
                    String errorMessage = decodeUnicodeString(msgInfo);
                    result.put("message", StringUtils.isNotEmpty(errorMessage) ? errorMessage : "操作失败");
                }
            } else {
                // 有嵌套结构，使用嵌套字段
                if (nestedSuccess && "SUCCESS".equals(nestedMsgCode)) {
                    result.put("success", true);
                    result.put("message", StringUtils.isNotEmpty(nestedMsgInfo) ? nestedMsgInfo : "查询成功");
                } else {
                    result.put("success", false);
                    String errorMessage = decodeUnicodeString(nestedMsgInfo);
                    result.put("message", StringUtils.isNotEmpty(errorMessage) ? errorMessage : "查询失败");
                }
            }

            log.debug("业务结果检查完成，成功: {}，消息: {}", result.get("success"), result.get("message"));

        } catch (Exception e) {
            log.error("检查SOAP业务结果失败", e);
            result.put("success", false);
            result.put("message", "解析业务结果失败: " + e.getMessage());
        }

        return result;
    }

    /**
     * 从SOAP响应中提取指定标签的JSON字符串
     *
     * @param soapResponse SOAP响应
     * @param resultTagName 结果标签名称
     * @return JSON字符串
     */
    private String extractJsonFromSoapResult(String soapResponse, String resultTagName) {
        try {
            String startTag = "<" + resultTagName + ">";
            String endTag = "</" + resultTagName + ">";

            int startIndex = soapResponse.indexOf(startTag);
            if (startIndex == -1) {
                log.warn("未找到{}开始标签", resultTagName);
                return null;
            }

            int contentStart = startIndex + startTag.length();
            int contentEnd = soapResponse.indexOf(endTag, contentStart);

            if (contentEnd > contentStart) {
                String jsonString = soapResponse.substring(contentStart, contentEnd);
                return jsonString.trim();
            } else {
                log.warn("未找到{}结束标签", resultTagName);
            }
        } catch (Exception e) {
            log.error("从SOAP响应中提取{}内容失败", resultTagName, e);
        }

        return null;
    }

    /**
     * 解码Unicode字符串
     *
     * @param unicodeString 包含Unicode编码的字符串
     * @return 解码后的字符串
     */
    private String decodeUnicodeString(String unicodeString) {
        if (StringUtils.isEmpty(unicodeString)) {
            return unicodeString;
        }

        try {
            // 处理 XXXX 格式的Unicode编码
            StringBuilder result = new StringBuilder();
            int i = 0;
            while (i < unicodeString.length()) {
                if (i < unicodeString.length() - 5 && unicodeString.charAt(i) == '\\' && unicodeString.charAt(i + 1) == 'u') {
                    // 提取4位十六进制数
                    String hex = unicodeString.substring(i + 2, i + 6);
                    try {
                        int codePoint = Integer.parseInt(hex, 16);
                        result.append((char) codePoint);
                        i += 6;
                    } catch (NumberFormatException e) {
                        // 如果不是有效的十六进制，直接添加字符
                        result.append(unicodeString.charAt(i));
                        i++;
                    }
                } else {
                    result.append(unicodeString.charAt(i));
                    i++;
                }
            }
            return result.toString();
        } catch (Exception e) {
            log.error("解码Unicode字符串失败: {}", unicodeString, e);
            return unicodeString;
        }
    }

}
